package com.nova.bluetooth.netWork;


import static com.nova.bluetooth.netWork.NetConstant.IDENTIFY_TOKEN;

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.nova.bluetooth.MyApp;
import com.nova.bluetooth.R;
import com.nova.bluetooth.helpUtils.MD5Util;
import com.nova.bluetooth.helpUtils.NetworkUtil;
import com.nova.bluetooth.helpUtils.SharePreferenceUtils;
import com.nova.bluetooth.netWork.request.GetRequest;
import com.nova.bluetooth.netWork.request.PostRequest;
import com.nova.bluetooth.netWork.result.BaseCommonResult;
import com.nova.bluetooth.netWork.result.BaseResult;
import com.nova.bluetooth.ui.ai.translate.BaiduTranslateRequest;

import java.io.IOException;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.util.HashMap;
import java.util.Map;

import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;

/**
 * Retrofit请求类
 */
public class RetrofitRequest {

    private static Gson gson = new Gson();

    //请求头添加token
    private static Interceptor interceptor = chain -> {
        String token = (String) SharePreferenceUtils.get(MyApp.getInstance(), IDENTIFY_TOKEN, "");
        Request original = chain.request();
        Request request = original.newBuilder()
                .header(IDENTIFY_TOKEN, token)
                .header("User-Agent", "com.nova.bluetooth")
                .header("identify_os", "Android")
                .method(original.method(), original.body())
                .build();
        return chain.proceed(request);
    };

    private static final Retrofit retrofit = RetrofitManage.createRetrofit(NetConstant.URL_BASE, interceptor);

//    private static final Retrofit chatGptRetrofit =
//            RetrofitManage.createChatGptRetrofit(NetConstant.URL_BASE_CHAT_GPT, interceptor);


    private static HashMap requestMap = new HashMap();

    private static String getRequestKey(Call<ResponseBody> call) {
        try {
            return MD5Util.get32BitUpper(call.request().url().toString());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 防止重复请求 CallEnqueue 执行网络请求的按钮可以使用这个方法
     *
     * @param call
     * @param clazz
     * @param resultHandler
     * @param <T>
     * @return
     */
    private static <T extends BaseResult> Call unRepetitionCallEnqueue(Call<ResponseBody> call,
                                                                       final Class<T> clazz,
                                                                       final ResultHandler<T> resultHandler) {
        String requestKey = getRequestKey(call);
        if (null == requestMap.get(requestKey)) {
            requestMap.put(requestKey, System.currentTimeMillis());
        } else {
            resultHandler.onAfterFailure();
            return call;
        }

        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                resultHandler.onBeforeResult();
                try {
                    ResponseBody body = response.body();
                    if (body == null) {
                        resultHandler.onServerError();
                        resultHandler.onAfterFailure();
                        return;
                    }
                    String string = body.string();
                    if (!TextUtils.isEmpty(string)) {
                        T t = new Gson().fromJson(string, clazz);
                        BaseCommonResult baseCommonResult = new Gson().fromJson(string,
                                BaseCommonResult.class);
                        if (baseCommonResult.getMsg() != null) {
                            Log.d("网络回调：callEnqueue", "callEnqueue：" + baseCommonResult.getMsg());
                        }


                        if (baseCommonResult.getCode() != null && baseCommonResult.getCode() == 4011) {  //未登录
//                            SharePreferenceUtils.clear(MyApplication.getInstance());
//
//                            publishMessageToMainActivity(Constant.APP_ORDER_LOGOUT_OTHER_DEVICE_LOGIN, "退出登录");
                            return;
                        }

                        resultHandler.onResult(t);
                    } else {
                        resultHandler.onResult(null);
                    }

                } catch (IOException | IllegalStateException e) {
                    e.printStackTrace();
                    resultHandler.onFailure(e);
                    resultHandler.onAfterFailure();
                }

                String requestKey = getRequestKey(call);
                requestMap.remove(requestKey);
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                String requestKey = getRequestKey(call);
                requestMap.remove(requestKey);

                resultHandler.onFailure(t);
                resultHandler.onAfterFailure();
            }
        });
        return call;
    }

    private static <T extends BaseResult> Call callEnqueue(Call<ResponseBody> call,
                                                           final Class<T> clazz,
                                                           final ResultHandler<T> resultHandler) {
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                resultHandler.onBeforeResult();
                try {
                    ResponseBody body = response.body();
                    if (body == null) {
                        resultHandler.onServerError();
                        resultHandler.onAfterFailure();
                        return;
                    }
                    String string = body.string();
                    if (!TextUtils.isEmpty(string)) {
                        T t = new Gson().fromJson(string, clazz);
                        BaseCommonResult baseCommonResult = new Gson().fromJson(string,
                                BaseCommonResult.class);
                        if (baseCommonResult.getMsg() != null) {
                            Log.d("网络回调：callEnqueue", "callEnqueue：" + baseCommonResult.getMsg());
                        }
                        if (baseCommonResult.getCode() != null && baseCommonResult.getCode() == 4011) {  //未登录
//                            SharePreferenceUtils.clear(MyApplication.getInstance());
//                            publishMessageToMainActivity(Constant.APP_ORDER_LOGOUT_OTHER_DEVICE_LOGIN, "退出登录");
                            return;
                        }
                        resultHandler.onResult(t);
                    } else {
                        resultHandler.onResult(null);
                    }
                } catch (JsonSyntaxException | IllegalStateException | IOException e) {
//                    e.printStackTrace();
                    resultHandler.onFailure(e);
                    resultHandler.onAfterFailure();
                }

            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                resultHandler.onFailure(t);
                resultHandler.onAfterFailure();
            }
        });
        return call;
    }


    /*****************************************************网络接口* *********************************************************/

    public static <T extends BaseResult> void baiduTranslation(BaiduTranslateRequest baiduTranslateRequest, final Class<T> clazz, final ResultHandler<T> resultHandler) {
        // 判断网络连接状况
        if (resultHandler.isNetDisconnected()) {
            resultHandler.onAfterFailure();
            return;
        }

        String jsonStr = gson.toJson(baiduTranslateRequest);
        TranslateRequest request = retrofit.create(TranslateRequest.class);
        RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json; " +
                "charset=utf-8"), jsonStr);
        // 构建请求
        Call<ResponseBody> call = request.baiduTranslation(body);
        callEnqueue(call, clazz, resultHandler);
    }



    /**
     * 发送GET网络请求
     *
     * @param url           请求地址
     * @param clazz         返回的数据类型
     * @param resultHandler 回调
     * @param <T>           泛型
     */
    public static <T extends BaseResult> Call sendGetRequest(String url, final Class<T> clazz,
                                                             final ResultHandler<T> resultHandler) {
        // 判断网络连接状况
        if (resultHandler.isNetDisconnected()) {
            resultHandler.onAfterFailure();
            return null;
        }

        GetRequest getRequest = retrofit.create(GetRequest.class);

        // 构建请求
        Call<ResponseBody> call = getRequest.getUrl(url);
        return unRepetitionCallEnqueue(call, clazz, resultHandler);
    }

    public static <T extends BaseResult> void sendPostBodyRequest(String url,
                                                                  Object requestBody,
                                                                  final Class<T> clazz,
                                                                  final ResultHandler<T> resultHandler) {
        // 判断网络连接状况
        if (resultHandler.isNetDisconnected()) {
            resultHandler.onAfterFailure();
            return;
        }

        String jsonStr = gson.toJson(requestBody);
        RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json; " +
                "charset=utf-8"), jsonStr);

        PostRequest postRequest = retrofit.create(PostRequest.class);
        // 构建请求
        Call<ResponseBody> call = postRequest.postBody(url, body);
        unRepetitionCallEnqueue(call, clazz, resultHandler);
    }

    /**
     * 发送post网络请求
     *
     * @param url           请求地址
     * @param paramMap      参数列表
     * @param clazz         返回的数据类型
     * @param resultHandler 回调
     * @param <T>           泛型
     */
    public static <T extends BaseResult> void sendPostRequest(String url,
                                                              Map<String, String> paramMap,
                                                              final Class<T> clazz,
                                                              final ResultHandler<T> resultHandler) {
        // 判断网络连接状况
        if (resultHandler.isNetDisconnected()) {
            resultHandler.onAfterFailure();
            return;
        }

        PostRequest postRequest = retrofit.create(PostRequest.class);
        // 构建请求
        Call<ResponseBody> call = postRequest.postMap(url, paramMap);
        unRepetitionCallEnqueue(call, clazz, resultHandler);
    }




    /**
     * 网络请求结果处理类
     *
     * @param <T> 请求结果封装对象
     */
    public static abstract class ResultHandler<T> {
        Context context;

        public ResultHandler(Context context) {
            this.context = context;
        }

        /**
         * 判断网络是否未连接
         *
         * @return
         */
        public boolean isNetDisconnected() {
            return NetworkUtil.isNetDisconnected(context);
        }

        /**
         * 请求成功之前
         */
        public abstract void onBeforeResult();

        /**
         * 请求成功时
         *
         * @param t 结果数据
         */
        public abstract void onResult(T t);

        /**
         * 服务器出错
         */
        public void onServerError() {
            // 服务器处理出错
            Toast.makeText(context, R.string.net_server_error, Toast.LENGTH_SHORT).show();
        }

        /**
         * 请求失败后的处理
         */
        public abstract void onAfterFailure();

        /**
         * 请求失败时的处理
         *
         * @param t
         */
        public void onFailure(Throwable t) {
            if (t instanceof SocketTimeoutException || t instanceof ConnectException) {
                // 连接异常
                if (NetworkUtil.isNetworkConnected(context)) {
                    // 服务器连接出错
                    Toast.makeText(context, R.string.net_server_connected_error,
                            Toast.LENGTH_SHORT).show();
                } else {
                    // 手机网络不通
                    Toast.makeText(context, R.string.net_not_connected, Toast.LENGTH_SHORT).show();
                }
            } else if (t instanceof Exception) {
                // 功能异常
                Log.e("retrofit onFailure", "网络错误,或是取消网络请求");
            }
        }
    }

}
